/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "geofence_service.h"

#include <ipc_skeleton.h>
#include "if_system_ability_manager.h"
#include "iservice_registry.h"
#include "system_ability_definition.h"

#include "geofence_permission.h"
#include "geofence_common.h"

namespace OHOS {
namespace Msdp {
namespace {
auto ms = DelayedSpSingleton<GeofenceService>::GetInstance();
const bool G_REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(ms.GetRefPtr());
constexpr int32_t MAX_DMUP_PARAM = 2;
}
GeofenceService::GeofenceService() : SystemAbility(MSDP_GEOFENCE_SERVICE_ID, true)
{
    GEOFENCE_HILOGD(GEOFENCE_MODULE_SERVICE, "Add SystemAbility");
}

GeofenceService::~GeofenceService() {}

void GeofenceService::OnDump()
{
    GEOFENCE_HILOGD(GEOFENCE_MODULE_SERVICE, "OnDump");
}

void GeofenceService::OnStart()
{
    GEOFENCE_HILOGI(GEOFENCE_MODULE_SERVICE, "Enter");
    if (ready_) {
        GEOFENCE_HILOGE(GEOFENCE_MODULE_SERVICE, "OnStart is ready, nothing to do.");
        return;
    }

    if (!Init()) {
        GEOFENCE_HILOGE(GEOFENCE_MODULE_SERVICE, "OnStart call init fail");
        return;
    }
    if (!Publish(DelayedSpSingleton<GeofenceService>::GetInstance())) {
        GEOFENCE_HILOGE(GEOFENCE_MODULE_SERVICE, "OnStart register to system ability manager failed");
        return;
    }
    ready_ = true;
    GEOFENCE_HILOGI(GEOFENCE_MODULE_SERVICE, "OnStart and add system ability success");
}

void GeofenceService::OnStop()
{
    GEOFENCE_HILOGI(GEOFENCE_MODULE_SERVICE, "Enter");
    if (!ready_) {
        return;
    }
    ready_ = false;
    GEOFENCE_HILOGI(GEOFENCE_MODULE_SERVICE, "Exit");
}

bool GeofenceService::Init()
{
    GEOFENCE_HILOGI(GEOFENCE_MODULE_SERVICE, "Enter");
    if (!geofenceConfig_) {
        geofenceConfig_ = std::make_shared<GeofenceConfig>();
    }
    if (!geofenceConfig_->Init()) {
        GEOFENCE_HILOGE(GEOFENCE_MODULE_SERVICE, "GeofenceConfig OnStart init fail");
        return false;
    }
    if (!geofencePolicy_) {
        geofencePolicy_ = std::make_shared<GeofencePolicy>(ms);
    }
    if (!geofencePolicy_->Init()) {
        GEOFENCE_HILOGE(GEOFENCE_MODULE_SERVICE, "GeofencePolicy OnStart init fail");
        return false;
    }
    if (!geofenceLocation_) {
        geofenceLocation_ = std::make_shared<GeofenceLocation>();
    }
    if (!geofenceLocation_->Init()) {
        GEOFENCE_HILOGE(GEOFENCE_MODULE_SERVICE, "GeofenceLocation OnStart init fail");
        return false;
    }
    if (!geofenceManager_) {
        geofenceManager_ = std::make_shared<GeofenceManager>();
    }
    if (!geofenceManager_->Init()) {
        GEOFENCE_HILOGE(GEOFENCE_MODULE_SERVICE, "GeofenceManager OnStart init fail");
        return false;
    }
    if (!geofenceStateMachine_) {
        geofenceStateMachine_ = std::make_shared<GeofenceStateMachine>(ms);
    }
    if (!geofenceStateMachine_->Init()) {
        GEOFENCE_HILOGE(GEOFENCE_MODULE_SERVICE, "GeofenceStateMachine OnStart init fail");
        return false;
    }
    if (!geofenceTrack_) {
        geofenceTrack_ = std::make_shared<GeofenceTrack>(ms);
    }
    if (!geofenceTrack_->Init()) {
        GEOFENCE_HILOGE(GEOFENCE_MODULE_SERVICE, "GeofenceTrack OnStart init fail");
        return false;
    }
    return true;
}

bool GeofenceService::IsServiceReady()
{
    return ready_;
}

std::shared_ptr<GeofenceConfig> GeofenceService::GetGeofenceConfig()
{
    return geofenceConfig_;
}

std::shared_ptr<GeofencePolicy> GeofenceService::GetGeofencePolicy()
{
    return geofencePolicy_;
}

std::shared_ptr<GeofenceLocation> GeofenceService::GetGeofenceLocation()
{
    return geofenceLocation_;
}

std::shared_ptr<GeofenceManager> GeofenceService::GetGeofenceManager()
{
    return geofenceManager_;
}

std::shared_ptr<GeofenceStateMachine> GeofenceService::GetGeofenceStateMachine()
{
    return geofenceStateMachine_;
}

std::shared_ptr<GeofenceTrack> GeofenceService::GetGeofenceTrack()
{
    return geofenceTrack_;
}

void GeofenceService::SubscribePoint(const GeofenceDataUtils::GeofenceType& type,
    const GeofenceDataUtils::PointOptions& pointOptions, const sptr<IgeofenceCallback>& callback)
{
    GEOFENCE_HILOGI(GEOFENCE_MODULE_SERVICE, "enter");
    geofencePolicy_->SubscribePoint(type, pointOptions, callback);
    GEOFENCE_HILOGI(GEOFENCE_MODULE_SERVICE, "exit");
}

void GeofenceService::UnSubscribePoint(const GeofenceDataUtils::GeofenceType& type,
    const GeofenceDataUtils::PointOptions& pointOptions, const sptr<IgeofenceCallback>& callback)
{
    GEOFENCE_HILOGI(GEOFENCE_MODULE_SERVICE, "enter");
    geofencePolicy_->UnSubscribePoint(type, pointOptions, callback);
    GEOFENCE_HILOGI(GEOFENCE_MODULE_SERVICE, "exit");
}

void GeofenceService::SubscribePoi(const GeofenceDataUtils::GeofenceType& type,
    const GeofenceDataUtils::PoiOptions& poiOptions, const sptr<IgeofenceCallback>& callback)
{
    GEOFENCE_HILOGI(GEOFENCE_MODULE_SERVICE, "enter");
    geofencePolicy_->SubscribePoi(type, poiOptions, callback);
    GEOFENCE_HILOGI(GEOFENCE_MODULE_SERVICE, "exit");
}

void GeofenceService::UnSubscribePoi(const GeofenceDataUtils::GeofenceType& type,
    const GeofenceDataUtils::PoiOptions& poiOptions, const sptr<IgeofenceCallback>& callback)
{
    GEOFENCE_HILOGI(GEOFENCE_MODULE_SERVICE, "enter");
    geofencePolicy_->UnSubscribePoi(type, poiOptions, callback);
    GEOFENCE_HILOGI(GEOFENCE_MODULE_SERVICE, "exit");
}

bool GeofenceService::SetFoolproofTactics(const GeofenceDataUtils::GeofenceType& type, double minuteTime)
{
    GEOFENCE_HILOGI(GEOFENCE_MODULE_SERVICE, "enter");
    return geofencePolicy_->SetFoolproofTactics(type, minuteTime);
}

int32_t GeofenceService::Dump(int32_t fd, const std::vector<std::u16string> &args)
{
    GEOFENCE_HILOGI(GEOFENCE_MODULE_SERVICE, "enter");
    GeofenceDump &geofenceDump = GeofenceDump::GetInstance();
    if ((args.empty()) || (args[0].size() != MAX_DMUP_PARAM)) {
        GEOFENCE_HILOGE(GEOFENCE_MODULE_SERVICE, "param cannot be empty or the length is not 2");
        dprintf(fd, "cmd param number is not equal to 2\n");
        geofenceDump.DumpHelp(fd);
        return -1;
    }
    bool helpRet = geofenceDump.DumpGeofenceHelp(fd, args);
    bool getTime = geofenceDump.GetPolicyFoolTacticsTime(fd, geofencePolicy_, args);
    bool getStateFlag = geofenceDump.GetPolicyStateFlag(fd, geofencePolicy_, args);
    bool total = helpRet + getTime + getStateFlag;
    if (!total) {
        dprintf(fd, "cmd param is error\n");
        geofenceDump.DumpHelp(fd);
        return -1;
    }
    GEOFENCE_HILOGI(GEOFENCE_MODULE_SERVICE, "exit");
    return 0;
}
} // namespace Msdp
} // namespace OHOS
